package com.box.app.arithmetic

@Suppress("EnumEntryName")
internal enum class Operator2(override val priority: Int = 1) : Operator {
    plus,
    minus,
    times(2),
    div(2),
    pow(2),
    rem(2),
    and,
    or,
    xor,
    shl,
    shr,
    ushr;

    fun call(a: Number, b: Number): Number {
        return when (this) {
            plus -> a.plus(b)
            minus -> a.minus(b)
            times -> a.times(b)
            div -> a.div(b)
            rem -> a.rem(b)
            pow -> a.pow(b)
            and -> a.and(b)
            or -> a.or(b)
            xor -> a.xor(b)
            shl -> a.shl(b)
            shr -> a.shr(b)
            ushr -> a.ushr(b)
        }
    }

    override fun toDescribe(isTight: Boolean): String {
        val describe = when (this) {
            plus -> "+"
            minus -> "-"
            times -> "*"
            div -> "/"
            rem -> "%"
            pow -> "**"
            and -> "&"
            or -> "|"
            xor -> "^"
            shl -> "<<"
            shr -> ">>"
            ushr -> ">>>"
        }
        return if (isTight) describe else " $describe "
    }

    override fun toString() = toDescribe(true)

    companion object {
        private fun maybeOf(s: String) = values().singleOrNull { it.toString() == s }

        fun of(s: String) = checkNotNull(maybeOf(s))
    }
}
